diff --git a/cypress/integration/layout.spec.js b/cypress/integration/layout.spec.js index 3c02e548..ed4bf9ce 100644 --- a/cypress/integration/layout.spec.js +++ b/cypress/integration/layout.spec.js @@ -1,224 +1,224 @@ /** * Copyright (C) 2019-2021 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ const url = '/browse/help/'; const statusUrl = 'https://status.softwareheritage.org'; describe('Test top-bar', function() { beforeEach(function() { cy.clearLocalStorage(); cy.visit(url); }); it('should should contain all navigation links', function() { cy.get('.swh-top-bar a') .should('have.length.of.at.least', 4) .and('be.visible') .and('have.attr', 'href'); }); - it('should show donate button on lg screen', function() { - cy.get('.swh-donate-link') - .should('be.visible'); - }); - it('should hide donate button on sm screen', function() { - cy.viewport(600, 800); - cy.get('.swh-donate-link') - .should('not.be.visible'); - }); + // it('should show donate button on lg screen', function() { + // cy.get('.swh-donate-link') + // .should('be.visible'); + // }); + // it('should hide donate button on sm screen', function() { + // cy.viewport(600, 800); + // cy.get('.swh-donate-link') + // .should('not.be.visible'); + // }); it('should hide full width switch on small screens', function() { cy.viewport(360, 740); cy.get('#swh-full-width-switch-container') .should('not.be.visible'); cy.viewport(600, 800); cy.get('#swh-full-width-switch-container') .should('not.be.visible'); cy.viewport(800, 600); cy.get('#swh-full-width-switch-container') .should('not.be.visible'); }); it('should show full width switch on large screens', function() { cy.viewport(1024, 768); cy.get('#swh-full-width-switch-container') .should('be.visible'); cy.viewport(1920, 1080); cy.get('#swh-full-width-switch-container') .should('be.visible'); }); it('should change container width when toggling Full width switch', function() { cy.get('#swh-web-content') .should('have.class', 'container') .should('not.have.class', 'container-fluid'); cy.should(() => { expect(JSON.parse(localStorage.getItem('swh-web-full-width'))).to.be.null; }); cy.get('#swh-full-width-switch') .click({force: true}); cy.get('#swh-web-content') .should('not.have.class', 'container') .should('have.class', 'container-fluid'); cy.should(() => { expect(JSON.parse(localStorage.getItem('swh-web-full-width'))).to.be.true; }); cy.get('#swh-full-width-switch') .click({force: true}); cy.get('#swh-web-content') .should('have.class', 'container') .should('not.have.class', 'container-fluid'); cy.should(() => { expect(JSON.parse(localStorage.getItem('swh-web-full-width'))).to.be.false; }); }); it('should restore container width when loading page again', function() { cy.visit(url) .get('#swh-web-content') .should('have.class', 'container') .should('not.have.class', 'container-fluid'); cy.get('#swh-full-width-switch') .click({force: true}); cy.visit(url) .get('#swh-web-content') .should('not.have.class', 'container') .should('have.class', 'container-fluid'); cy.get('#swh-full-width-switch') .click({force: true}); cy.visit(url) .get('#swh-web-content') .should('have.class', 'container') .should('not.have.class', 'container-fluid'); }); function genStatusResponse(status, statusCode) { return { 'result': { 'status': [ { 'id': '5f7c4c567f50b304c1e7bd5f', 'name': 'Save Code Now', 'updated': '2020-11-30T13:51:21.151Z', 'status': 'Operational', 'status_code': 100 }, { 'id': '5f7c4c6f8338bc04b7f476fe', 'name': 'Source Code Crawlers', 'updated': '2020-11-30T13:51:21.151Z', 'status': status, 'status_code': statusCode } ] } }; } it('should display swh status widget when data are available', function() { const statusTestData = [ { status: 'Operational', statusCode: 100, color: 'green' }, { status: 'Scheduled Maintenance', statusCode: 200, color: 'blue' }, { status: 'Degraded Performance', statusCode: 300, color: 'yellow' }, { status: 'Partial Service Disruption', statusCode: 400, color: 'yellow' }, { status: 'Service Disruption', statusCode: 500, color: 'red' }, { status: 'Security Event', statusCode: 600, color: 'red' } ]; for (let i = 0; i < statusTestData.length; ++i) { cy.intercept(`${statusUrl}/**`, { body: genStatusResponse(statusTestData[i].status, statusTestData[i].statusCode) }).as(`getSwhStatusData`); cy.visit(url); cy.wait(`@getSwhStatusData`); cy.get('.swh-current-status-indicator').should('have.class', statusTestData[i].color); cy.get('#swh-current-status-description').should('have.text', statusTestData[i].status); } }); it('should not display swh status widget when data are not available', function() { cy.intercept(`${statusUrl}/**`, { body: {} }).as('getSwhStatusData'); cy.visit(url); cy.wait('@getSwhStatusData'); cy.get('.swh-current-status').should('not.exist'); }); }); describe('Test navbar', function() { it('should redirect to search page when submitting search form in navbar', function() { const keyword = 'python'; cy.get('#swh-origins-search-top-input') .type(keyword); cy.get('.swh-search-navbar') .submit(); cy.url() .should('include', `${this.Urls.browse_search()}?q=${keyword}`); }); }); describe('Test footer', function() { beforeEach(function() { cy.visit(url); }); it('should be visible', function() { cy.get('footer') .should('be.visible'); }); it('should have correct copyright years', function() { const currentYear = new Date().getFullYear(); const copyrightText = '(C) 2015–' + currentYear.toString(); cy.get('footer') .should('contain', copyrightText); }); it('should contain link to Web API', function() { cy.get('footer') .get(`a[href="${this.Urls.api_1_homepage()}"]`) .should('contain', 'Web API'); }); }); diff --git a/swh/web/templates/layout.html b/swh/web/templates/layout.html index c10c3fda..8c550b94 100644 --- a/swh/web/templates/layout.html +++ b/swh/web/templates/layout.html @@ -1,291 +1,291 @@ {% comment %} Copyright (C) 2015-2021 The Software Heritage developers See the AUTHORS file at the top-level directory of this distribution License: GNU Affero General Public License version 3, or any later version See top-level LICENSE file for more information {% endcomment %} <!DOCTYPE html> {% load js_reverse %} {% load static %} {% load render_bundle from webpack_loader %} {% load swh_templatetags %} <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>{% block title %}{% endblock %}</title> {% render_bundle 'vendors' %} {% render_bundle 'webapp' %} {% render_bundle 'guided_tour' %} <script> /* @licstart The following is the entire license notice for the JavaScript code in this page. Copyright (C) 2015-2021 The Software Heritage developers This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. @licend The above is the entire license notice for the JavaScript code in this page. */ </script> <script> SWH_CONFIG = {{swh_client_config|jsonify}}; swh.webapp.sentryInit(SWH_CONFIG.sentry_dsn); </script> <script src="{% url 'js_reverse' %}" type="text/javascript"></script> <script> swh.webapp.setSwhObjectIcons({{ swh_object_icons|jsonify }}); </script> {{ request.user.is_authenticated|json_script:"swh_user_logged_in" }} {% block header %}{% endblock %} <link rel="icon" href="{% static 'img/icons/swh-logo-32x32.png' %}" sizes="32x32" /> <link rel="icon" href="{% static 'img/icons/swh-logo-archive-192x192.png' %}" sizes="192x192" /> <link rel="apple-touch-icon-precomposed" href="{% static 'img/icons/swh-logo-archive-180x180.png' %}" /> <link rel="search" type="application/opensearchdescription+xml" title="Software Heritage archive of public source code" href="{% static 'xml/swh-opensearch.xml' %}"> <meta name="msapplication-TileImage" content="{% static 'img/icons/swh-logo-archive-270x270.png' %}" /> {% if not swh_web_dev and not swh_web_staging %} <!-- Matomo --> <script type="text/javascript"> var _paq = window._paq = window._paq || []; _paq.push(['trackPageView']); (function() { var u="https://piwik.inria.fr/"; _paq.push(['setTrackerUrl', u+'matomo.php']); _paq.push(['setSiteId', '59']); var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); })(); </script> <!-- End Matomo Code --> {% endif %} </head> <body class="hold-transition layout-fixed sidebar-mini"> <a id="top"></a> <div class="wrapper"> <div class="swh-top-bar"> <ul> <li class="swh-position-left"> <div id="swh-full-width-switch-container" class="custom-control custom-switch d-none d-lg-block d-xl-block"> <input type="checkbox" class="custom-control-input" id="swh-full-width-switch" onclick="swh.webapp.fullWidthToggled(event)"> <label class="custom-control-label font-weight-normal" for="swh-full-width-switch">Full width</label> </div> </li> <li> <a href="https://www.softwareheritage.org">Home</a> </li> <li> <a href="https://forge.softwareheritage.org/">Development</a> </li> <li> <a href="https://docs.softwareheritage.org/devel/">Documentation</a> </li> - <li> + {% comment %} <li> <a class="swh-donate-link" href="https://www.softwareheritage.org/donate">Donate</a> - </li> + </li> {% endcomment %} <li class="swh-position-right"> <a href="{{ status.server_url }}" target="_blank" class="swh-current-status mr-3 d-none d-lg-inline-block d-xl-inline-block"> <span id="swh-current-status-description">Operational</span> <i class="swh-current-status-indicator green"></i> </a> {% url 'logout' as logout_url %} {% if user.is_authenticated %} Logged in as {% if 'OIDC' in user.backend %} <a id="swh-login" href="{% url 'oidc-profile' %}"><strong>{{ user.username }}</strong></a>, <a href= "{% url 'oidc-logout' %}?next_path={% url 'logout' %}?remote_user=1">logout</a> {% else %} <strong id="swh-login">{{ user.username }}</strong>, <a href="{{ logout_url }}">logout</a> {% endif %} {% elif oidc_enabled %} {% if request.path != logout_url %} <a id="swh-login" href="{% url 'oidc-login' %}?next_path={{ request.build_absolute_uri }}">login</a> {% else %} <a id="swh-login" href="{% url 'oidc-login' %}">login</a> {% endif %} {% else %} {% if request.path != logout_url %} <a id="swh-login" href="{% url 'login' %}?next={{ request.build_absolute_uri }}">login</a> {% else %} <a id="swh-login" href="{% url 'login' %}">login</a> {% endif %} {% endif %} </li> </ul> </div> <iframe class="swh-fundraising-banner-iframe" src="{% url 'swh-fundraising-banner' %}"></iframe> <nav class="main-header navbar navbar-expand-lg navbar-light navbar-static-top" id="swh-navbar"> <div class="navbar-header"> <a class="nav-link swh-push-menu" data-widget="pushmenu" data-enable-remember="true" href="#"> <i class="mdi mdi-24px mdi-menu mdi-fw" aria-hidden="true"></i> </a> </div> <div class="navbar" style="width: 94%;"> <div class="swh-navbar-content"> {% block navbar-content %}{% endblock %} {% if request.resolver_match.url_name != 'swh-web-homepage' and request.resolver_match.url_name != 'browse-search' %} <form class="form-horizontal d-none d-md-flex input-group swh-search-navbar needs-validation" id="swh-origins-search-top"> <input class="form-control" placeholder="Enter a SWHID to resolve or keyword(s) to search for in origin URLs" type="text" id="swh-origins-search-top-input" oninput="swh.webapp.validateSWHIDInput(this)" required/> <div class="input-group-append"> <button class="btn btn-primary" type="submit"> <i class="swh-search-icon mdi mdi-24px mdi-magnify" aria-hidden="true"></i> </button> </div> </form> {% endif %} </div> </div> </nav> </div> <aside class="swh-sidebar main-sidebar sidebar-no-expand sidebar-light-primary elevation-4"> <a href="{% url 'swh-web-homepage' %}" class="brand-link"> <img class="brand-image" src="{% static 'img/swh-logo.png' %}"> <div class="brand-text sitename" href="{% url 'swh-web-homepage' %}"> <span class="first-word">Software</span> <span class="second-word">Heritage</span> </div> </a> <a href="/" class="swh-words-logo"> <div class="swh-words-logo-swh"> <span class="first-word">Software</span> <span class="second-word">Heritage</span> </div> <span>Archive</span> </a> <div class="sidebar"> <nav class="mt-2"> <ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false"> <li class="nav-header">Features</li> <li class="nav-item swh-search-item" title="Search archived software"> <a href="{% url 'browse-search' %}" class="nav-link swh-search-link"> <i style="color: #e20026;" class="nav-icon mdi mdi-24px mdi-magnify"></i> <p>Search</p> </a> </li> <li class="nav-item swh-vault-item" title="Download archived software from the Vault"> <a href="{% url 'browse-vault' %}" class="nav-link swh-vault-link"> <i style="color: #e20026;" class="nav-icon mdi mdi-24px mdi-download"></i> <p>Downloads</p> </a> </li> <li class="nav-item swh-origin-save-item" title="Request the saving of a software origin into the archive"> <a href="{% url 'origin-save' %}" class="nav-link swh-origin-save-link"> <i style="color: #e20026;" class="nav-icon mdi mdi-24px mdi-camera"></i> <p>Save code now</p> </a> </li> <li class="nav-item swh-help-item" title="How to browse the archive ?"> {% if user.is_authenticated and user.is_staff or "swh.ambassador" in user.get_all_permissions %} <a href="#" class="nav-link swh-help-link" onclick="swh.guided_tour.guidedTourButtonClick(event)"> {% else %} <a href="{% url 'browse-help' %}" class="nav-link swh-help-link"> {% endif %} <i style="color: #e20026;" class="nav-icon mdi mdi-24px mdi-help-circle"></i> <p>Help</p> </a> </li> {% if user.is_authenticated and user.is_staff or ADMIN_LIST_DEPOSIT_PERMISSION in user.get_all_permissions %} <li class="nav-header">Administration</li> {% if user.is_staff %} <li class="nav-item swh-origin-save-admin-item" title="Save code now administration"> <a href="{% url 'admin-origin-save' %}" class="nav-link swh-origin-save-admin-link"> <i style="color: #fecd1b;" class="nav-icon mdi mdi-24px mdi-camera"></i> <p>Save code now</p> </a> </li> {% endif %} <li class="nav-item swh-deposit-admin-item" title="Deposit administration"> <a href="{% url 'admin-deposit' %}" class="nav-link swh-deposit-admin-link"> <i style="color: #fecd1b;" class="nav-icon mdi mdi-24px mdi-folder-upload"></i> <p>Deposit</p> </a> </li> {% endif %} </ul> </nav> </div> </aside> <div class="content-wrapper"> <section class="content"> <div class="container" id="swh-web-content"> {% if swh_web_staging %} <div class="swh-corner-ribbon">Staging<br/>v{{ swh_web_version }}</div> {% elif swh_web_dev %} <div class="swh-corner-ribbon">Development<br/>v{{ swh_web_version|split:"+"|first }}</div> {% endif %} {% block content %}{% endblock %} </div> </section> </div> {% include "includes/global-modals.html" %} <footer class="footer"> <div class="container text-center"> <a href="https://www.softwareheritage.org">Software Heritage</a> — Copyright (C) 2015–{% now "Y" %}, The Software Heritage developers. License: <a href="https://www.gnu.org/licenses/agpl.html">GNU AGPLv3+</a>. <br/> The source code of Software Heritage <em>itself</em> is available on our <a href="https://forge.softwareheritage.org/">development forge</a>. <br/> The source code files <em>archived</em> by Software Heritage are available under their own copyright and licenses. <br/> <span class="link-color">Terms of use: </span> <a href="https://www.softwareheritage.org/legal/bulk-access-terms-of-use/">Archive access</a>, <a href="https://www.softwareheritage.org/legal/api-terms-of-use/">API</a>- <a href="https://www.softwareheritage.org/contact/">Contact</a>- <a href="{% url 'jslicenses' %}" rel="jslicense">JavaScript license information</a>- <a href="{% url 'api-1-homepage' %}">Web API</a><br/> {% if "production" not in DJANGO_SETTINGS_MODULE %} swh-web v{{ swh_web_version }} {% endif %} </div> </footer> <div id="back-to-top"> <a href="#top"><img alt="back to top" src="{% static 'img/arrow-up-small.png' %}" /></a> </div> <script> swh.webapp.setContainerFullWidth(); var statusServerURL = {{ status.server_url|jsonify }}; var statusJsonPath = {{ status.json_path|jsonify }}; swh.webapp.initStatusWidget(statusServerURL + statusJsonPath); </script> </body> </html>